﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Evaluant.Uss.Commands;
using Amazon.SimpleDB.Model;

namespace EussSimpleDBProvider
{
    class SimpleDBCommandProcessor : ICommandProcessor
    {
        SimpleDBEngine m_Engine = null;

        public SimpleDBCommandProcessor(SimpleDBEngine engine)
        {
            m_Engine = engine;
        }

        #region ICommandProcessor Members

        private string m_NewId;
        public string NewId
        {
            get
            {
                return m_NewId;
            }
            set
            {
                m_NewId = value;
            }
        }

        SimpleDBEngine Engine { get { return m_Engine; } }

        public void Process(Command command)
        {
            
        }

        public void Process(CreateEntityCommand command)
        {
            PutAttributesRequest pa = GetPutAttributes(command);

            ReplaceableAttribute ra = new ReplaceableAttribute();
            ra.Name = Engine.IdColumn;
            ra.Value = command.ParentId;
            pa.Attribute.Add(ra);

            ReplaceableAttribute typeattr = new ReplaceableAttribute();
            typeattr.Name = Engine.TypeColumn;
            typeattr.Value = command.Type;
            pa.Attribute.Add(typeattr);

            Engine.DBClient.PutAttributes(pa);
        }

        public void Process(CompoundCreateCommand c)
        {
            PutAttributesRequest pa = GetPutAttributes(c);

            ReplaceableAttribute idattr = new ReplaceableAttribute();
            idattr.Name = Engine.IdColumn;
            idattr.Value = c.ParentId;
            pa.Attribute.Add(idattr);

            ReplaceableAttribute typeattr = new ReplaceableAttribute();
            typeattr.Name = Engine.TypeColumn;
            typeattr.Value = c.Type;
            pa.Attribute.Add(typeattr);

            foreach (CreateAttributeCommand cc in c.InnerCommands)
            {
                ReplaceableAttribute ra = new ReplaceableAttribute();
                ra.Name = cc.Name;
                ra.Value = SimpleDBConversion.ToSDBString(cc.Value);
                ra.Replace = false;

                pa.Attribute.Add(ra);
            }

            Engine.DBClient.PutAttributes(pa);
        }

        PutAttributesRequest GetPutAttributes(Command c)
        {
            PutAttributesRequest pa = new PutAttributesRequest();
            pa.DomainName = Engine.DomainName;

            if (c is EntityCommand)
            {
                EntityCommand ec = c as EntityCommand;
                pa.ItemName = Engine.GetName(ec.Type, ec.ParentId);
            }
            else if(c is CompoundUpdateCommand)
            {
                CompoundUpdateCommand cuc = c as CompoundUpdateCommand;
                pa.ItemName = Engine.GetName(cuc.ParentType, cuc.ParentId);
            }
            else if (c is AttributeCommand)
            {
                AttributeCommand ac = c as AttributeCommand;
                pa.ItemName = Engine.GetName(ac.ParentType, ac.ParentId);
            }
            else if (c is ReferenceCommand)
            {
                ReferenceCommand rc = c as ReferenceCommand;
                pa.ItemName = Engine.GetName(rc.ParentType, rc.ParentId);
            }
            else
            {
                throw new NotSupportedException("Don't know what to do with command type: " + c.GetType().FullName);
            }

            return pa;
        }

        void AddAttributeCommand(PutAttributesRequest pa, AttributeCommand command)
        {
            ReplaceableAttribute ra = new ReplaceableAttribute();
            ra.Name = command.Name;
            ra.Value = SimpleDBConversion.ToSDBString(command.Value);

            if (command is CreateAttributeCommand)
                ra.Replace = false;
            else if (command is UpdateAttributeCommand)
                ra.Replace = true;

            pa.Attribute.Add(ra);
        }

        void AddReferenceCommand(PutAttributesRequest pa, CreateReferenceCommand command)
        {
            ReplaceableAttribute ra = new ReplaceableAttribute();
            ra.Name = command.Role;
            ra.Value = Engine.GetName(command.ChildType, command.ChildId);
            ra.Replace = false;
            pa.Attribute.Add(ra);
        }

        public void Process(CompoundUpdateCommand c)
        {
            PutAttributesRequest pa = GetPutAttributes(c);

            foreach (AttributeCommand cc in c.InnerCommands)
                AddAttributeCommand(pa, cc);

            Engine.DBClient.PutAttributes(pa);
        }

        public void Process(DeleteEntityCommand command)
        {
            DeleteAttributesRequest da = new DeleteAttributesRequest();
            da.DomainName = Engine.DomainName;
            da.ItemName = Engine.GetName(command.Type, command.ParentId);

            Engine.DBClient.DeleteAttributes(da);
        }

        public void Process(CreateAttributeCommand command)
        {
            ProcessAttributeCommand(command);
        }

        void ProcessAttributeCommand(AttributeCommand command)
        {
            PutAttributesRequest pa = GetPutAttributes(command);
            AddAttributeCommand(pa, command);

            Engine.DBClient.PutAttributes(pa);
        }

        public void Process(UpdateAttributeCommand command)
        {
            ProcessAttributeCommand(command);
        }

        public void Process(DeleteAttributeCommand command)
        {
            DeleteAttributesRequest da = new DeleteAttributesRequest();
            da.DomainName = Engine.DomainName;
            da.ItemName = Engine.GetName(command.ParentType, command.ParentId);

            Amazon.SimpleDB.Model.Attribute attr = new Amazon.SimpleDB.Model.Attribute();
            attr.Name = command.Name;
            da.Attribute.Add(attr);

            Engine.DBClient.DeleteAttributes(da);
        }

        public void Process(CreateReferenceCommand command)
        {
            PutAttributesRequest pa = GetPutAttributes(command);
            AddReferenceCommand(pa, command);
            
            Engine.DBClient.PutAttributes(pa);
        }

        public void Process(DeleteReferenceCommand command)
        {
            DeleteAttributesRequest da = new DeleteAttributesRequest();
            da.DomainName = Engine.DomainName;
            da.ItemName = Engine.GetName(command.ParentType, command.ParentId);

            Amazon.SimpleDB.Model.Attribute attr = new Amazon.SimpleDB.Model.Attribute();
            attr.Name = command.Role;
            attr.Value = Engine.GetName(command.ChildType, command.ChildId);
            da.Attribute.Add(attr);

            Engine.DBClient.DeleteAttributes(da);
        }

        #endregion
    }
}
